package com.uuah.server.config.spring;

import java.util.Collection;
import java.util.Map;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;

import com.uuah.api.lifecycle.IDisposable;
import com.uuah.api.lifecycle.Initialisable;
import com.uuah.config.i18n.MessageFactory;
import com.uuah.exception.lifecycle.InitialisationException;
import com.uuah.server.api.lifecycle.ILifecycleManager;
import com.uuah.server.config.registry.AbstractRegistry;
import com.uuah.server.exception.registry.RegistrationException;
import com.uuah.server.lifecycle.ContainerManagedLifecyclePhase;
import com.uuah.server.lifecycle.GenericLifecycleManager;
import com.uuah.utils.CollectionUtils;
import com.uuah.utils.StringUtils;

/**
 *
 * TODO comment ...
 *
 * <p>
 * update record:updator，update time，update content and version
 * </p>
 *
 * @author <a href="jonny_quan@hotmail.com">jonny</a>
 * @date 2009 2009-3-27 下午01:26:17
 * @version 1.0.0
 */
public class SpringRegistry extends AbstractRegistry {
	public static final String REGISTRY_ID = "com.uuah.server.Registry.Spring";

	public static final String SPRING_APPLICATION_CONTEXT = "springApplicationContext";

	protected ApplicationContext applicationContext;

	public SpringRegistry() {
		super(REGISTRY_ID);
	}

	public SpringRegistry(String id) {
		super(id);
	}

	public SpringRegistry(ApplicationContext applicationContext) {
		super(REGISTRY_ID);
		this.applicationContext = applicationContext;
	}

	public SpringRegistry(String id, ApplicationContext applicationContext) {
		super(id);
		this.applicationContext = applicationContext;
	}

	// @Override
	protected void doInitialise() throws InitialisationException {
		if (applicationContext instanceof ConfigurableApplicationContext) {
			((ConfigurableApplicationContext) applicationContext).refresh();
		}
	}

	protected void doDispose() {
		if (applicationContext instanceof ConfigurableApplicationContext
				&& ((ConfigurableApplicationContext) applicationContext)
						.isActive()) {
			((ConfigurableApplicationContext) applicationContext).close();
		}
	}

	protected ILifecycleManager createLifecycleManager() {
		GenericLifecycleManager lcm = new GenericLifecycleManager();
		lcm.registerLifecycle(new ContainerManagedLifecyclePhase(
				Initialisable.PHASE_NAME, Initialisable.class,
				IDisposable.PHASE_NAME));
		lcm.registerLifecycle(new ContainerManagedLifecyclePhase(
				IDisposable.PHASE_NAME, IDisposable.class,
				Initialisable.PHASE_NAME));
		return lcm;
	}

	public Object lookupObject(String key) {
		if (StringUtils.isBlank(key)) {
			logger.warn(MessageFactory.createStaticMessage(
					"Detected a lookup attempt with an empty or null key")
					.getMessage(), new Throwable().fillInStackTrace());
			return null;
		}

		if (key.equals(SPRING_APPLICATION_CONTEXT)
				&& applicationContext != null) {
			return applicationContext;
		} else {
			try {
				return applicationContext.getBean(key);
			} catch (NoSuchBeanDefinitionException e) {
				if (logger.isDebugEnabled()) {
					logger.debug(e.getMessage());
				}
				return null;
			}
		}
	}

	public Collection lookupObjects(Class type) {
		try {
			Map map = applicationContext.getBeansOfType(type);
			return map.values();
		} catch (Exception e) {
			if (logger.isDebugEnabled()) {
				logger.debug(e.getMessage());
			}
			return CollectionUtils.EMPTY_COLLECTION;
		}
	}

	public void registerObject(String key, Object value)
			throws RegistrationException {
		throw new UnsupportedOperationException(
				"Registry is read-only so objects cannot be registered or unregistered.");
	}

	public void registerObject(String key, Object value, Object metadata)
			throws RegistrationException {
		throw new UnsupportedOperationException(
				"Registry is read-only so objects cannot be registered or unregistered.");
	}

	public void registerObjects(Map objects) throws RegistrationException {
		throw new UnsupportedOperationException(
				"Registry is read-only so objects cannot be registered or unregistered.");
	}

	public void unregisterObject(String key) {
		throw new UnsupportedOperationException(
				"Registry is read-only so objects cannot be registered or unregistered.");
	}

	public void unregisterObject(String key, Object metadata)
			throws RegistrationException {
		throw new UnsupportedOperationException(
				"Registry is read-only so objects cannot be registered or unregistered.");
	}

	public boolean isReadOnly() {
		return true;
	}
}
